package com.xhorse.lockplatform.comm.util;

import java.io.*;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.*;

public class ZipUtil {

	private File zipFile;

	/**
	 * 构造器
	 * 
	 * @param pathName
	 *            要压缩的zip文件路径
	 */
	public ZipUtil(String pathName) {
		zipFile = new File(pathName);
	}

	/**
	 * 多文件/文件夹的压缩方法，传入多个文件夹目录，一起压缩到指定压缩目录
	 * 
	 * @param pathName
	 *            源文件路径
	 */
	public void compress(String... pathName) {
		ZipOutputStream zos = null;
		try {
			// 决定最终压缩数据放在哪里
			FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
			// 循环冗余校验
			CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream,
					new CRC32());
			zos = new ZipOutputStream(cos);
			String basedir = "";
			for (int i = 0; i < pathName.length; i++) {
				compress(new File(pathName[i]), zos, basedir);
			}
			zos.close();
			fileOutputStream.close();
			cos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 单文件/文件夹压缩方法
	 * 
	 * @param srcpathName
	 *            源文件路径
	 */
	public void compress(String srcpathName) {
		File file = new File(srcpathName);
		if (!file.exists()) {
			throw new RuntimeException(srcpathName + "文件路径不存在");
		}
		try {
			FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
			CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream,
					new CRC32());
			ZipOutputStream zos = new ZipOutputStream(cos);
			String basedir = "";
			compress(file, zos, basedir);
			zos.close();
			fileOutputStream.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void compress(File file, ZipOutputStream out, String basedir) {
		if (file.isDirectory()) { // 判断是目录还是文件
			compressDirectory(file, out, basedir);
		} else {
			compressFile(file, out, basedir);
		}
	}

	/**
	 * 压缩一个目录
	 * 
	 * @param dir
	 *            源文件夹路径
	 * @param out
	 *            输出流
	 * @param baseDir
	 *            节点文件路径
	 */
	private void compressDirectory(File dir, ZipOutputStream out, String baseDir) {
		if (!dir.exists()) {
			return;
		}
		File[] files = dir.listFiles();
		for (int i = 0; i < files.length; i++) {
			// 递归调用，直到找到文件最底层
			compress(files[i], out, dir.getName() + File.separator);
		}
	}

	/**
	 * 压缩文件
	 * 
	 * @param file
	 *            文件路径
	 * @param out
	 *            zipoutpustream输出流
	 * @param baseDir
	 *            节点文件路径
	 */
	private void compressFile(File file, ZipOutputStream out, String baseDir) {
		if (!file.exists()) {
			return;
		}
		try {
			BufferedInputStream bis = new BufferedInputStream(
					new FileInputStream(file));
			ZipEntry zipEntry = new ZipEntry(baseDir + file.getName());
			out.putNextEntry(zipEntry);
			int index;
			byte[] buffer = new byte[1024];
			while ((index = bis.read(buffer)) != -1) {
				out.write(buffer, 0, index);
			}
			bis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 文件解压
	 * @param srcFile 源文件
	 * @param descDir 目标路径
	 * @throws IOException
	 */
	@SuppressWarnings("resource")
	public static void unZipFiles(File srcFile, String descDir)
			throws IOException {
		ZipFile zipFile = new ZipFile(srcFile, Charset.forName("GBK")); // 解决中文文件乱码问题
		for(Enumeration<? extends ZipEntry> entries =  zipFile.entries(); entries.hasMoreElements();){
			ZipEntry entry = entries.nextElement();
			String zipEntryName = entry.getName();
			String tartgetPath = (descDir + "/"+ zipEntryName).replaceAll("\\*", "/"); 
			File file = new File(tartgetPath.substring(0, tartgetPath.lastIndexOf('/'))); //获取压缩包当中子文件夹
			if(!file.exists()){
				file.mkdirs();
			}
			if(new File(tartgetPath).isDirectory()){ //判断当前entry对应的是不是文件夹，是的话跳出循环，直到找到第一个文件
				continue;
			}
			InputStream is = zipFile.getInputStream(entry);
			FileOutputStream fos = new FileOutputStream(tartgetPath);
			byte[] buffer = new byte[1024*1024];
			int index = 0;
			while((index=is.read(buffer))!=-1){
				fos.write(buffer, 0, index);
			}
			is.close();
			fos.close();
			
		}
		System.out.println("******************解压完毕********************");
	}
}
